﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
using System.Diagnostics;

using ShootSearch.Core;
using ShootSearch.FileSystem;
using ShootSearch.Logging;

namespace ShootSearch.Indexers
{
    public class DBIndexer: IIndexer
    {
        protected DBIndexerConfig config;
        protected DbConnection dbConnection;
        protected DbCommand dbCommand;


        public DBIndexer()
        {
            config = new DBIndexerConfig();
        }

        #region IIndexer Members

        public bool Create(params object[] args)
        {
            bool result = true;

            if (config!=null)
            {
                try
                {
                    if (dbConnection != null)
                    {
                        dbConnection.Close();
                    }

                    
                    object objConnection = config.Connection.GetObject(config.ConnectionString);
                    dbConnection = (DbConnection)objConnection;
                  
                    dbConnection.Open();
                    dbCommand = dbConnection.CreateCommand();
                    result = InitializeCommand();

                }
                catch (Exception ex)
                {
                    Log.Error(Logger, "Connection error!" , ex);
                    result = false;
                }


            }
            else result = false;

            return result;
        }

       

        public bool Add(object doc)
        {
            bool parsed = Parse(doc);

            if (parsed)
            {
                try
                {
                    parsed = dbCommand.ExecuteNonQuery() > 0;
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex);
                    parsed = false;
                }
                
            }

            return parsed;
        }

      

        public void Close()
        {
            if (dbConnection != null
                && dbConnection.State == ConnectionState.Open)
            {
                try
                {
                    dbConnection.Close();
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex);
                }
            }
        }

        #endregion

        #region IConfigable Members

        public ShootSearch.Core.SpiderManConfig Config
        {
            get { return config; }
            set
            {
                if (value is DBIndexerConfig)
                {
                    this.config = value as DBIndexerConfig;
                }
            }
        }

        #endregion
        
        #region IDisposable Members

        public void Dispose()
        {
            Close();
        }

        #endregion


        protected bool InitializeCommand()
        {
            List<string> keys = new List<string>();
            List<string> keyparams = new List<string>();

            for (int i = 0; i < config.InterestedAttributes.Count; i++)
            {
                DBIndexerConfig.DBIndexerAttribute att = config.InterestedAttributes[i];
                string key = att.ColumnName;

                keys.Add(string.Format(config.UniqueNameSpliter, key));
                keyparams.Add("@" + key);

                DbParameter dbparam = dbCommand.CreateParameter();
                dbparam.ParameterName = "@" + key;
                dbparam.DbType = att.DbType;
                dbCommand.Parameters.Add(dbparam);
            }

            if (keyparams.Count > 0)
            {
                dbCommand.CommandText = string.Format(config.Insert,
                       config.Table,
                       string.Join(",", keys.ToArray()),
                       string.Join(",", keyparams.ToArray()));
                return true;
            }
            else return false;

        }

        protected virtual bool Parse(object input)
        {
            if (input is FileObject)
            {
                FileObjectText item = new FileObjectText((FileObject)input);
                int valueCount = 0;
                for (int i = 0; i < config.InterestedAttributes.Count; i++)
                {
                    DBIndexerConfig.DBIndexerAttribute att = config.InterestedAttributes[i];
                    string value = att.ParseValue(item);
                    if (!att.AllowNull && value == null) return false;
                    dbCommand.Parameters[i].Value = att.GetDbTypeValue(value);

                    if (value != null)
                    {
                        valueCount++;
                    }

                }

                if (valueCount > 0)
                {
                    return true;
                }
                else return false;


            }
            else return false;
        }

        #region IIndexer Members

        public log4net.ILog Logger { get; set; }

        #endregion
    }
}
